package com.example.demo.framework.config;

import com.alibaba.fastjson.JSON;
import com.example.demo.base.OutSideBizException;
import com.example.demo.consts.enums.ResponseStatus;
import com.example.demo.framework.exception.GlobalExceptionResolver;
import com.example.demo.framework.filters.tracer.TraceFilter;
import com.example.demo.framework.filters.tracer.TraceInfo;
import com.example.demo.framework.interceptors.FeignTraceInterceptor;
import com.example.demo.framework.rule.TraceRoundRobinRule;
import com.example.demo.framework.utils.TraceUtils;
import com.example.demo.response.ApiResult;
import com.netflix.loadbalancer.RoundRobinRule;
import feign.Client;
import feign.Request;
import feign.RequestInterceptor;
import feign.Response;
import feign.Util;
import feign.codec.ErrorDecoder;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.cloud.netflix.ribbon.SpringClientFactory;
import org.springframework.cloud.openfeign.ribbon.CachingSpringLoadBalancerFactory;
import org.springframework.cloud.openfeign.ribbon.LoadBalancerFeignClient;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;
import org.springframework.http.HttpStatus;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLSocketFactory;
import javax.servlet.Filter;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;

/**
 * @Auther: miaoguoxin
 * @Date: 2020/3/20 14:42
 * @Description:
 */
@Slf4j
public class TraceAutoConfiguration {

    @Bean
    public GlobalExceptionResolver globalExceptionResolver(){
        return new GlobalExceptionResolver();
    }
    @Bean
    public Filter traceFilter(){
       return new TraceFilter();
    }

    /**
     * 自定义feign.Client
     * @return
     */
    @Bean
    public Client feignIPClient(CachingSpringLoadBalancerFactory cachingFactory,
                                SpringClientFactory clientFactory) {
        return new LoadBalancerFeignClient(new FeignIPClient(),cachingFactory, clientFactory);
    }

    @Bean
    public RequestInterceptor requestInterceptor(){
        return new FeignTraceInterceptor();
    }

    @Bean
    public ErrorDecoder errorDecoder() {
        return (methodKey, response) -> {
            try {
                TraceInfo traceInfo = TraceUtils.get();
                String json = Util.toString(response.body().asReader(StandardCharsets.UTF_8));
                log.info("响应信息:{}",json);
            } catch (IOException e) {
                log.error("错误:{}",e);
            }
            return new OutSideBizException(ResponseStatus.MESSAGE_REPEAT_SEND);
        };
    }

    @Bean
   // @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
    public TraceRoundRobinRule traceRoundRobinRule(){
        return new TraceRoundRobinRule();
    }

    public class FeignIPClient extends Client.Default {
        Logger logger = LoggerFactory.getLogger("FeignIPClient");

        /**
         * 默认构造方法
         */
        public FeignIPClient(){
            this(null,null);
        }

        /**
         * Null parameters imply platform defaults.
         * @param sslContextFactory
         * @param hostnameVerifier
         */
        public FeignIPClient(SSLSocketFactory sslContextFactory, HostnameVerifier hostnameVerifier) {
            super(sslContextFactory, hostnameVerifier);
        }

        @Override
        public Response execute(Request request, Request.Options options) throws IOException {
            //打印目标节点IP
            logger.info("请求至：---> {},---{}",request.url(),request.requestTemplate().path());
            TraceInfo traceInfo = TraceUtils.get();
            traceInfo.buildNext(request.requestTemplate().path(),request.url());
            return super.execute(request, options);
        }
    }
}
